//------------------------------------------------------------------------------
// X2D Game Engine
// Copyright (C) 2006-2008 Janusz Kowalski
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------

#include "SDL.h"

#include "mainLoop.h"
#include "RawVector.h"

typedef struct {
  // Function returns how much time may pass before the next call.
  TimeT (*fn)(Uint32, void*);
  void *data;
} FnInfo;

static RawVector<FnInfo> FnList;

static bool keepRunning;

// Add callback function to the main loop
void mainLoop_addFn(TimeT(*fn)(Uint32, void*), void *data) {
  FnInfo fi;
  fi.fn=fn;
  fi.data=data;
  FnList.add(fi);
}

// Remove callback function from the main loop
void mainLoop_removeFn(TimeT(*fn)(Uint32, void*), void *data) {
  FnInfo fi;
  fi.fn=fn;
  fi.data=data;
  for(unsigned i=0; i<FnList.size(); i++)
    if(FnList[i].fn == fn && FnList[i].data == data)
      FnList.removeElementAt(i);
}

template<class T> T min(T a, T b) { return a<b?a:b; }

// Run the loop only once.
TimeT mainLoop_tick() {
  TimeT t = 1000;
  for(unsigned i=0; i<FnList.size(); i++) {
    t=min(t, FnList[i].fn(SDL_GetTicks(), FnList[i].data));
  }
  return t;
}

// Run the main loop.
// It keeps running until there are no functions to call.
void mainLoop_run() {
  keepRunning=true;
  while(keepRunning && (FnList.size()>0)) {
    Uint32 t = mainLoop_tick();
    if(t>5) SDL_Delay(t);
  }
}

// Stop running.
void mainLoop_stop() {
  keepRunning=false;
}
